home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i107: Xlisp version 1.6 (xlisp1.6), Part01/06
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- Submitted by: seismo!utah-cs!b-davis (Brad Davis)
- Mod.sources: Volume 6, Issue 107
- Archive-name: xlisp1.6/Part01
-
- [ This unpacks, compiles, and runs a couple of the demo programs on
- my 4.2BSD Vax750. I have not tried it on a PC. --r$ ]
-
-
- -------------------------------- Cut Here --------------------------------
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # xlbfun.c
- # xlcont.c
- # xldbug.c
- # xldmem.c
- # xleval.c
- # This archive created: Mon Jul 14 10:21:31 1986
- export PATH; PATH=/bin:$PATH
- if test -f 'xlbfun.c'
- then
- echo shar: will not over-write existing file "'xlbfun.c'"
- else
- cat << \SHAR_EOF > 'xlbfun.c'
- /* xlbfun.c - xlisp basic built-in functions */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
-
- #include "xlisp.h"
-
- /* external variables */
- extern NODE ***xlstack,*xlenv;
- extern NODE *s_car,*s_cdr,*s_nth,*s_get,*s_svalue,*s_splist,*s_aref;
- extern NODE *s_lambda,*s_macro;
- extern NODE *s_comma,*s_comat;
- extern NODE *s_unbound;
- extern char gsprefix[];
- extern int gsnumber;
-
- /* forward declarations */
- FORWARD NODE *bquote1();
- FORWARD NODE *defun();
- FORWARD NODE *makesymbol();
-
- /* xeval - the built-in function 'eval' */
- NODE *xeval(args)
- NODE *args;
- {
- NODE ***oldstk,*expr,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&expr,(NODE **)NULL);
-
- /* get the expression to evaluate */
- expr = xlarg(&args);
- xllastarg(args);
-
- /* evaluate the expression */
- val = xleval(expr);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the expression evaluated */
- return (val);
- }
-
- /* xapply - the built-in function 'apply' */
- NODE *xapply(args)
- NODE *args;
- {
- NODE ***oldstk,*fun,*arglist,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&fun,&arglist,(NODE **)NULL);
-
- /* get the function and argument list */
- fun = xlarg(&args);
- arglist = xlmatch(LIST,&args);
- xllastarg(args);
-
- /* if the function is a symbol, get its value */
- if (symbolp(fun))
- fun = xleval(fun);
-
- /* apply the function to the arguments */
- val = xlapply(fun,arglist);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the expression evaluated */
- return (val);
- }
-
- /* xfuncall - the built-in function 'funcall' */
- NODE *xfuncall(args)
- NODE *args;
- {
- NODE ***oldstk,*fun,*arglist,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&fun,&arglist,(NODE **)NULL);
-
- /* get the function and argument list */
- fun = xlarg(&args);
- arglist = args;
-
- /* if the function is a symbol, get its value */
- if (symbolp(fun))
- fun = xleval(fun);
-
- /* apply the function to the arguments */
- val = xlapply(fun,arglist);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the expression evaluated */
- return (val);
- }
-
- /* xquote - built-in function to quote an expression */
- NODE *xquote(args)
- NODE *args;
- {
- NODE *val;
-
- /* get the argument */
- val = xlarg(&args);
- xllastarg(args);
-
- /* return the quoted expression */
- return (val);
- }
-
- /* xfunction - built-in function to quote a function */
- NODE *xfunction(args)
- NODE *args;
- {
- NODE *val;
-
- /* get the argument */
- val = xlarg(&args);
- xllastarg(args);
-
- /* create a closure for lambda expressions */
- if (consp(val) && car(val) == s_lambda)
- val = cons(val,xlenv);
-
- /* otherwise, get the value of a symbol */
- else if (symbolp(val))
- val = xlgetvalue(val);
-
- /* otherwise, its an error */
- else
- xlerror("not a function",val);
-
- /* return the function */
- return (val);
- }
-
- /* xlambda - lambda function */
- NODE *xlambda(args)
- NODE *args;
- {
- NODE ***oldstk,*fargs,*closure;
-
- /* create a new stack frame */
- oldstk = xlsave(&fargs,&closure,(NODE **)NULL);
-
- /* get the formal argument list */
- fargs = xlmatch(LIST,&args);
-
- /* create a new function definition */
- closure = cons(fargs,args);
- closure = cons(s_lambda,closure);
- closure = cons(closure,xlenv);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the closure */
- return (closure);
- }
-
- /* xbquote - back quote function */
- NODE *xbquote(args)
- NODE *args;
- {
- NODE ***oldstk,*expr,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&expr,(NODE **)NULL);
-
- /* get the expression */
- expr = xlarg(&args);
- xllastarg(args);
-
- /* fill in the template */
- val = bquote1(expr);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* bquote1 - back quote helper function */
- LOCAL NODE *bquote1(expr)
- NODE *expr;
- {
- NODE ***oldstk,*val,*list,*last,*new;
-
- /* handle atoms */
- if (atom(expr))
- val = expr;
-
- /* handle (comma <expr>) */
- else if (car(expr) == s_comma) {
- if (atom(cdr(expr)))
- xlfail("bad comma expression");
- val = xleval(car(cdr(expr)));
- }
-
- /* handle ((comma-at <expr>) ... ) */
- else if (consp(car(expr)) && car(car(expr)) == s_comat) {
- oldstk = xlsave(&list,&val,(NODE **)NULL);
- if (atom(cdr(car(expr))))
- xlfail("bad comma-at expression");
- list = xleval(car(cdr(car(expr))));
- for (last = NIL; consp(list); list = cdr(list)) {
- new = consa(car(list));
- if (last)
- rplacd(last,new);
- else
- val = new;
- last = new;
- }
- if (last)
- rplacd(last,bquote1(cdr(expr)));
- else
- val = bquote1(cdr(expr));
- xlstack = oldstk;
- }
-
- /* handle any other list */
- else {
- oldstk = xlsave(&val,(NODE **)NULL);
- val = consa(NIL);
- rplaca(val,bquote1(car(expr)));
- rplacd(val,bquote1(cdr(expr)));
- xlstack = oldstk;
- }
-
- /* return the result */
- return (val);
- }
-
- /* xset - built-in function set */
- NODE *xset(args)
- NODE *args;
- {
- NODE *sym,*val;
-
- /* get the symbol and new value */
- sym = xlmatch(SYM,&args);
- val = xlarg(&args);
- xllastarg(args);
-
- /* assign the symbol the value of argument 2 and the return value */
- setvalue(sym,val);
-
- /* return the result value */
- return (val);
- }
-
- /* xsetq - built-in function setq */
- NODE *xsetq(args)
- NODE *args;
- {
- NODE ***oldstk,*arg,*sym,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&sym,&val,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* handle each pair of arguments */
- while (arg) {
- sym = xlmatch(SYM,&arg);
- val = xlevarg(&arg);
- xlsetvalue(sym,val);
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result value */
- return (val);
- }
-
- /* xsetf - built-in function 'setf' */
- NODE *xsetf(args)
- NODE *args;
- {
- NODE ***oldstk,*arg,*place,*value;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&place,&value,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* handle each pair of arguments */
- while (arg) {
-
- /* get place and value */
- place = xlarg(&arg);
- value = xlevarg(&arg);
-
- /* check the place form */
- if (symbolp(place))
- xlsetvalue(place,value);
- else if (consp(place))
- placeform(place,value);
- else
- xlfail("bad place form");
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the value */
- return (value);
- }
-
- /* placeform - handle a place form other than a symbol */
- LOCAL placeform(place,value)
- NODE *place,*value;
- {
- NODE ***oldstk,*fun,*arg1,*arg2;
- int i;
-
- /* check the function name */
- if ((fun = xlmatch(SYM,&place)) == s_get) {
- oldstk = xlsave(&arg1,&arg2,(NODE **)NULL);
- arg1 = xlevmatch(SYM,&place);
- arg2 = xlevmatch(SYM,&place);
- xllastarg(place);
- xlputprop(arg1,value,arg2);
- xlstack = oldstk;
- }
- else if (fun == s_svalue || fun == s_splist) {
- oldstk = xlsave(&arg1,(NODE **)NULL);
- arg1 = xlevmatch(SYM,&place);
- xllastarg(place);
- if (fun == s_svalue)
- setvalue(arg1,value);
- else
- setplist(arg1,value);
- xlstack = oldstk;
- }
- else if (fun == s_car || fun == s_cdr) {
- oldstk = xlsave(&arg1,(NODE **)NULL);
- arg1 = xlevmatch(LIST,&place);
- xllastarg(place);
- if (consp(arg1))
- if (fun == s_car)
- rplaca(arg1,value);
- else
- rplacd(arg1,value);
- xlstack = oldstk;
- }
- else if (fun == s_nth) {
- oldstk = xlsave(&arg1,&arg2,(NODE **)NULL);
- arg1 = xlevmatch(INT,&place);
- arg2 = xlevmatch(LIST,&place);
- xllastarg(place);
- for (i = (int)getfixnum(arg1); i > 0 && consp(arg2); --i)
- arg2 = cdr(arg2);
- if (consp(arg2))
- rplaca(arg2,value);
- xlstack = oldstk;
- }
-
- else if (fun == s_aref) {
- oldstk = xlsave(&arg1,&arg2,(NODE **)NULL);
- arg1 = xlevmatch(VECT,&place);
- arg2 = xlevmatch(INT,&place); i = (int)getfixnum(arg2);
- xllastarg(place);
- if (i < 0 || i >= getsize(arg1))
- xlerror("index out of range",arg2);
- setelement(arg1,i,value);
- xlstack = oldstk;
- }
- else
- xlfail("bad place form");
- }
-
- /* xdefun - built-in function 'defun' */
- NODE *xdefun(args)
- NODE *args;
- {
- return (defun(args,s_lambda));
- }
-
- /* xdefmacro - built-in function 'defmacro' */
- NODE *xdefmacro(args)
- NODE *args;
- {
- return (defun(args,s_macro));
- }
-
- /* defun - internal function definition routine */
- LOCAL NODE *defun(args,type)
- NODE *args,*type;
- {
- NODE ***oldstk,*sym,*fargs,*closure;
-
- /* create a new stack frame */
- oldstk = xlsave(&sym,&fargs,&closure,(NODE **)NULL);
-
- /* get the function symbol and formal argument list */
- sym = xlmatch(SYM,&args);
- fargs = xlmatch(LIST,&args);
-
- /* create a new function definition */
- closure = cons(fargs,args);
- closure = cons(type,closure);
- closure = cons(closure,xlenv);
-
- /* make the symbol point to a new function definition */
- xlsetvalue(sym,closure);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the function symbol */
- return (sym);
- }
-
- /* xgensym - generate a symbol */
- NODE *xgensym(args)
- NODE *args;
- {
- char sym[STRMAX+1];
- NODE *x;
-
- /* get the prefix or number */
- if (args) {
- x = xlarg(&args);
- switch (ntype(x)) {
- case STR:
- strcpy(gsprefix,getstring(x));
- break;
- case INT:
- gsnumber = getfixnum(x);
- break;
- default:
- xlerror("bad argument type",x);
- }
- }
- xllastarg(args);
-
- /* create the pname of the new symbol */
- sprintf(sym,"%s%d",gsprefix,gsnumber++);
-
- /* make a symbol with this print name */
- return (xlmakesym(sym,DYNAMIC));
- }
-
- /* xmakesymbol - make a new uninterned symbol */
- NODE *xmakesymbol(args)
- NODE *args;
- {
- return (makesymbol(args,FALSE));
- }
-
- /* xintern - make a new interned symbol */
- NODE *xintern(args)
- NODE *args;
- {
- return (makesymbol(args,TRUE));
- }
-
- /* makesymbol - make a new symbol */
- LOCAL NODE *makesymbol(args,iflag)
- NODE *args; int iflag;
- {
- NODE ***oldstk,*pname,*val;
- char *str;
-
- /* create a new stack frame */
- oldstk = xlsave(&pname,(NODE **)NULL);
-
- /* get the print name of the symbol to intern */
- pname = xlmatch(STR,&args);
- xllastarg(args);
-
- /* make the symbol */
- str = getstring(pname);
- val = (iflag ? xlenter(str,DYNAMIC) : xlmakesym(str,DYNAMIC));
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the symbol */
- return (val);
- }
-
- /* xsymname - get the print name of a symbol */
- NODE *xsymname(args)
- NODE *args;
- {
- NODE *sym;
-
- /* get the symbol */
- sym = xlmatch(SYM,&args);
- xllastarg(args);
-
- /* return the print name */
- return (getpname(sym));
- }
-
- /* xsymvalue - get the value of a symbol */
- NODE *xsymvalue(args)
- NODE *args;
- {
- NODE *sym,*val;
-
- /* get the symbol */
- sym = xlmatch(SYM,&args);
- xllastarg(args);
-
- /* get the global value */
- while ((val = getvalue(sym)) == s_unbound)
- xlcerror("try evaluating symbol again","unbound variable",sym);
-
- /* return its value */
- return (val);
- }
-
- /* xsymplist - get the property list of a symbol */
- NODE *xsymplist(args)
- NODE *args;
- {
- NODE *sym;
-
- /* get the symbol */
- sym = xlmatch(SYM,&args);
- xllastarg(args);
-
- /* return the property list */
- return (getplist(sym));
- }
-
- /* xget - get the value of a property */
- NODE *xget(args)
- NODE *args;
- {
- NODE *sym,*prp;
-
- /* get the symbol and property */
- sym = xlmatch(SYM,&args);
- prp = xlmatch(SYM,&args);
- xllastarg(args);
-
- /* retrieve the property value */
- return (xlgetprop(sym,prp));
- }
-
- /* xputprop - set the value of a property */
- NODE *xputprop(args)
- NODE *args;
- {
- NODE *sym,*val,*prp;
-
- /* get the symbol and property */
- sym = xlmatch(SYM,&args);
- val = xlarg(&args);
- prp = xlmatch(SYM,&args);
- xllastarg(args);
-
- /* set the property value */
- xlputprop(sym,val,prp);
-
- /* return the value */
- return (val);
- }
-
- /* xremprop - remove a property value from a property list */
- NODE *xremprop(args)
- NODE *args;
- {
- NODE *sym,*prp;
-
- /* get the symbol and property */
- sym = xlmatch(SYM,&args);
- prp = xlmatch(SYM,&args);
- xllastarg(args);
-
- /* remove the property */
- xlremprop(sym,prp);
-
- /* return nil */
- return (NIL);
- }
-
- /* xhash - compute the hash value of a string or symbol */
- NODE *xhash(args)
- NODE *args;
- {
- char *str;
- NODE *val;
- int len;
-
- /* get the string and the table length */
- val = xlarg(&args);
- len = (int)getfixnum(xlmatch(INT,&args));
- xllastarg(args);
-
- /* get the string */
- if (symbolp(val))
- str = getstring(getpname(val));
- else if (stringp(val))
- str = getstring(val);
- else
- xlerror("bad argument type",val);
-
- /* return the hash index */
- return (cvfixnum((FIXNUM)hash(str,len)));
- }
-
- /* xaref - array reference function */
- NODE *xaref(args)
- NODE *args;
- {
- NODE *array,*index;
- int i;
-
- /* get the array and the index */
- array = xlmatch(VECT,&args);
- index = xlmatch(INT,&args); i = (int)getfixnum(index);
- xllastarg(args);
-
- /* range check the index */
- if (i < 0 || i >= getsize(array))
- xlerror("array index out of bounds",index);
-
- /* return the array element */
- return (getelement(array,i));
- }
-
- /* xmkarray - make a new array */
- NODE *xmkarray(args)
- NODE *args;
- {
- int size;
-
- /* get the size of the array */
- size = (int)getfixnum(xlmatch(INT,&args));
- xllastarg(args);
-
- /* create the array */
- return (newvector(size));
- }
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'xlcont.c'
- then
- echo shar: will not over-write existing file "'xlcont.c'"
- else
- cat << \SHAR_EOF > 'xlcont.c'
- /* xlcont - xlisp control built-in functions */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
-
- #include "xlisp.h"
-
- /* external variables */
- extern NODE ***xlstack,*xlenv,*xlvalue;
- extern NODE *s_unbound;
- extern NODE *s_evalhook,*s_applyhook;
- extern NODE *true;
-
- /* external routines */
- extern NODE *xlxeval();
-
- /* forward declarations */
- FORWARD NODE *let();
- FORWARD NODE *prog();
- FORWARD NODE *progx();
- FORWARD NODE *doloop();
-
- /* xcond - built-in function 'cond' */
- NODE *xcond(args)
- NODE *args;
- {
- NODE ***oldstk,*arg,*list,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&list,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* initialize the return value */
- val = NIL;
-
- /* find a predicate that is true */
- while (arg) {
-
- /* get the next conditional */
- list = xlmatch(LIST,&arg);
-
- /* evaluate the predicate part */
- if (val = xlevarg(&list)) {
-
- /* evaluate each expression */
- while (list)
- val = xlevarg(&list);
-
- /* exit the loop */
- break;
- }
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the value */
- return (val);
- }
-
- /* xcase - built-in function 'case' */
- NODE *xcase(args)
- NODE *args;
- {
- NODE ***oldstk,*key,*arg,*clause,*list,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&key,&arg,&clause,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* get the key expression */
- key = xlevarg(&arg);
-
- /* initialize the return value */
- val = NIL;
-
- /* find a case that matches */
- while (arg) {
-
- /* get the next case clause */
- clause = xlmatch(LIST,&arg);
-
- /* compare the key list against the key */
- if ((list = xlarg(&clause)) == true ||
- (listp(list) && keypresent(key,list)) ||
- eql(key,list)) {
-
- /* evaluate each expression */
- while (clause)
- val = xlevarg(&clause);
-
- /* exit the loop */
- break;
- }
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the value */
- return (val);
- }
-
- /* keypresent - check for the presence of a key in a list */
- LOCAL int keypresent(key,list)
- NODE *key,*list;
- {
- for (; consp(list); list = cdr(list))
- if (eql(car(list),key))
- return (TRUE);
- return (FALSE);
- }
-
- /* xand - built-in function 'and' */
- NODE *xand(args)
- NODE *args;
- {
- NODE ***oldstk,*arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,(NODE **)NULL);
-
- /* initialize */
- arg = args;
- val = true;
-
- /* evaluate each argument */
- while (arg)
-
- /* get the next argument */
- if ((val = xlevarg(&arg)) == NIL)
- break;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result value */
- return (val);
- }
-
- /* xor - built-in function 'or' */
- NODE *xor(args)
- NODE *args;
- {
- NODE ***oldstk,*arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,(NODE **)NULL);
-
- /* initialize */
- arg = args;
- val = NIL;
-
- /* evaluate each argument */
- while (arg)
- if ((val = xlevarg(&arg)))
- break;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result value */
- return (val);
- }
-
- /* xif - built-in function 'if' */
- NODE *xif(args)
- NODE *args;
- {
- NODE ***oldstk,*testexpr,*thenexpr,*elseexpr,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&testexpr,&thenexpr,&elseexpr,(NODE **)NULL);
-
- /* get the test expression, then clause and else clause */
- testexpr = xlarg(&args);
- thenexpr = xlarg(&args);
- elseexpr = (args ? xlarg(&args) : NIL);
- xllastarg(args);
-
- /* evaluate the appropriate clause */
- val = xleval(xleval(testexpr) ? thenexpr : elseexpr);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the last value */
- return (val);
- }
-
- /* xlet - built-in function 'let' */
- NODE *xlet(args)
- NODE *args;
- {
- return (let(args,TRUE));
- }
-
- /* xletstar - built-in function 'let*' */
- NODE *xletstar(args)
- NODE *args;
- {
- return (let(args,FALSE));
- }
-
- /* let - common let routine */
- LOCAL NODE *let(args,pflag)
- NODE *args; int pflag;
- {
- NODE ***oldstk,*newenv,*arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&newenv,&arg,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* create a new environment frame */
- newenv = xlframe(xlenv);
-
- /* get the list of bindings and bind the symbols */
- if (!pflag) xlenv = newenv;
- dobindings(xlmatch(LIST,&arg),newenv);
- if (pflag) xlenv = newenv;
-
- /* execute the code */
- for (val = NIL; arg; )
- val = xlevarg(&arg);
-
- /* unbind the arguments */
- xlenv = cdr(xlenv);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* xprog - built-in function 'prog' */
- NODE *xprog(args)
- NODE *args;
- {
- return (prog(args,TRUE));
- }
-
- /* xprogstar - built-in function 'prog*' */
- NODE *xprogstar(args)
- NODE *args;
- {
- return (prog(args,FALSE));
- }
-
- /* prog - common prog routine */
- LOCAL NODE *prog(args,pflag)
- NODE *args; int pflag;
- {
- NODE ***oldstk,*newenv,*arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&newenv,&arg,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* create a new environment frame */
- newenv = xlframe(xlenv);
-
- /* get the list of bindings and bind the symbols */
- if (!pflag) xlenv = newenv;
- dobindings(xlmatch(LIST,&arg),newenv);
- if (pflag) xlenv = newenv;
-
- /* execute the code */
- tagblock(arg,&val);
-
- /* unbind the arguments */
- xlenv = cdr(xlenv);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* xgo - built-in function 'go' */
- NODE *xgo(args)
- NODE *args;
- {
- NODE *label;
-
- /* get the target label */
- label = xlarg(&args);
- xllastarg(args);
-
- /* transfer to the label */
- xlgo(label);
- }
-
- /* xreturn - built-in function 'return' */
- NODE *xreturn(args)
- NODE *args;
- {
- NODE *val;
-
- /* get the return value */
- val = (args ? xlarg(&args) : NIL);
- xllastarg(args);
-
- /* return from the inner most block */
- xlreturn(val);
- }
-
- /* xprog1 - built-in function 'prog1' */
- NODE *xprog1(args)
- NODE *args;
- {
- return (progx(args,1));
- }
-
- /* xprog2 - built-in function 'prog2' */
- NODE *xprog2(args)
- NODE *args;
- {
- return (progx(args,2));
- }
-
- /* progx - common progx code */
- LOCAL NODE *progx(args,n)
- NODE *args; int n;
- {
- NODE ***oldstk,*arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&val,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* evaluate the first n expressions */
- while (n--)
- val = xlevarg(&arg);
-
- /* evaluate each remaining argument */
- while (arg)
- xlevarg(&arg);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the last test expression value */
- return (val);
- }
-
- /* xprogn - built-in function 'progn' */
- NODE *xprogn(args)
- NODE *args;
- {
- NODE ***oldstk,*arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* evaluate each remaining argument */
- for (val = NIL; arg; )
- val = xlevarg(&arg);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the last test expression value */
- return (val);
- }
-
- /* xdo - built-in function 'do' */
- NODE *xdo(args)
- NODE *args;
- {
- return (doloop(args,TRUE));
- }
-
- /* xdostar - built-in function 'do*' */
- NODE *xdostar(args)
- NODE *args;
- {
- return (doloop(args,FALSE));
- }
-
- /* doloop - common do routine */
- LOCAL NODE *doloop(args,pflag)
- NODE *args; int pflag;
- {
- NODE ***oldstk,*newenv,*arg,*blist,*clist,*test,*rval;
- int rbreak;
-
- /* create a new stack frame */
- oldstk = xlsave(&newenv,&arg,&blist,&clist,&test,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* get the list of bindings */
- blist = xlmatch(LIST,&arg);
-
- /* create a new environment frame */
- newenv = xlframe(xlenv);
-
- /* bind the symbols */
- if (!pflag) xlenv = newenv;
- dobindings(blist,newenv);
- if (pflag) xlenv = newenv;
-
- /* get the exit test and result forms */
- clist = xlmatch(LIST,&arg);
- test = xlarg(&clist);
-
- /* execute the loop as long as the test is false */
- rbreak = FALSE;
- while (xleval(test) == NIL) {
-
- /* execute the body of the loop */
- if (tagblock(arg,&rval)) {
- rbreak = TRUE;
- break;
- }
-
- /* update the looping variables */
- doupdates(blist,pflag);
- }
-
- /* evaluate the result expression */
- if (!rbreak)
- for (rval = NIL; consp(clist); )
- rval = xlevarg(&clist);
-
- /* unbind the arguments */
- xlenv = cdr(xlenv);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (rval);
- }
-
- /* xdolist - built-in function 'dolist' */
- NODE *xdolist(args)
- NODE *args;
- {
- NODE ***oldstk,*arg,*clist,*sym,*list,*val,*rval;
- int rbreak;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&clist,&sym,&list,&val,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* get the control list (sym list result-expr) */
- clist = xlmatch(LIST,&arg);
- sym = xlmatch(SYM,&clist);
- list = xlevmatch(LIST,&clist);
- val = (clist ? xlarg(&clist) : NIL);
-
- /* initialize the local environment */
- xlenv = xlframe(xlenv);
- xlbind(sym,NIL,xlenv);
-
- /* loop through the list */
- rbreak = FALSE;
- for (; consp(list); list = cdr(list)) {
-
- /* bind the symbol to the next list element */
- xlsetvalue(sym,car(list));
-
- /* execute the loop body */
- if (tagblock(arg,&rval)) {
- rbreak = TRUE;
- break;
- }
- }
-
- /* evaluate the result expression */
- if (!rbreak) {
- xlsetvalue(sym,NIL);
- rval = xleval(val);
- }
-
- /* unbind the arguments */
- xlenv = cdr(xlenv);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (rval);
- }
-
- /* xdotimes - built-in function 'dotimes' */
- NODE *xdotimes(args)
- NODE *args;
- {
- NODE ***oldstk,*arg,*clist,*sym,*val,*rval;
- int rbreak,cnt,i;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&clist,&sym,&val,(NODE **)NULL);
-
- /* initialize */
- arg = args;
-
- /* get the control list (sym list result-expr) */
- clist = xlmatch(LIST,&arg);
- sym = xlmatch(SYM,&clist);
- cnt = getfixnum(xlevmatch(INT,&clist));
- val = (clist ? xlarg(&clist) : NIL);
-
- /* initialize the local environment */
- xlenv = xlframe(xlenv);
- xlbind(sym,NIL,xlenv);
-
- /* loop through for each value from zero to cnt-1 */
- rbreak = FALSE;
- for (i = 0; i < cnt; i++) {
-
- /* bind the symbol to the next list element */
- xlsetvalue(sym,cvfixnum((FIXNUM)i));
-
- /* execute the loop body */
- if (tagblock(arg,&rval)) {
- rbreak = TRUE;
- break;
- }
- }
-
- /* evaluate the result expression */
- if (!rbreak) {
- xlsetvalue(sym,cvfixnum((FIXNUM)cnt));
- rval = xleval(val);
- }
-
- /* unbind the arguments */
- xlenv = cdr(xlenv);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (rval);
- }
-
- /* xcatch - built-in function 'catch' */
- NODE *xcatch(args)
- NODE *args;
- {
- NODE ***oldstk,*tag,*arg,*val;
- CONTEXT cntxt;
-
- /* create a new stack frame */
- oldstk = xlsave(&tag,&arg,(NODE **)NULL);
-
- /* initialize */
- tag = xlevarg(&args);
- arg = args;
- val = NIL;
-
- /* establish an execution context */
- xlbegin(&cntxt,CF_THROW,tag);
-
- /* check for 'throw' */
- if (setjmp(cntxt.c_jmpbuf))
- val = xlvalue;
-
- /* otherwise, evaluate the remainder of the arguments */
- else {
- while (arg)
- val = xlevarg(&arg);
- }
- xlend(&cntxt);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* xthrow - built-in function 'throw' */
- NODE *xthrow(args)
- NODE *args;
- {
- NODE *tag,*val;
-
- /* get the tag and value */
- tag = xlarg(&args);
- val = (args ? xlarg(&args) : NIL);
- xllastarg(args);
-
- /* throw the tag */
- xlthrow(tag,val);
- }
-
- /* xerror - built-in function 'error' */
- NODE *xerror(args)
- NODE *args;
- {
- char *emsg; NODE *arg;
-
- /* get the error message and the argument */
- emsg = getstring(xlmatch(STR,&args));
- arg = (args ? xlarg(&args) : s_unbound);
- xllastarg(args);
-
- /* signal the error */
- xlerror(emsg,arg);
- }
-
- /* xcerror - built-in function 'cerror' */
- NODE *xcerror(args)
- NODE *args;
- {
- char *cmsg,*emsg; NODE *arg;
-
- /* get the correction message, the error message, and the argument */
- cmsg = getstring(xlmatch(STR,&args));
- emsg = getstring(xlmatch(STR,&args));
- arg = (args ? xlarg(&args) : s_unbound);
- xllastarg(args);
-
- /* signal the error */
- xlcerror(cmsg,emsg,arg);
-
- /* return nil */
- return (NIL);
- }
-
- /* xbreak - built-in function 'break' */
- NODE *xbreak(args)
- NODE *args;
- {
- char *emsg; NODE *arg;
-
- /* get the error message */
- emsg = (args ? getstring(xlmatch(STR,&args)) : "**BREAK**");
- arg = (args ? xlarg(&args) : s_unbound);
- xllastarg(args);
-
- /* enter the break loop */
- xlbreak(emsg,arg);
-
- /* return nil */
- return (NIL);
- }
-
- /* xcleanup - built-in function 'clean-up' */
- NODE *xcleanup(args)
- NODE *args;
- {
- xllastarg(args);
- xlcleanup();
- }
-
- /* xcontinue - built-in function 'continue' */
- NODE *xcontinue(args)
- NODE *args;
- {
- xllastarg(args);
- xlcontinue();
- }
-
- /* xerrset - built-in function 'errset' */
- NODE *xerrset(args)
- NODE *args;
- {
- NODE ***oldstk,*expr,*flag,*val;
- CONTEXT cntxt;
-
- /* create a new stack frame */
- oldstk = xlsave(&expr,&flag,(NODE **)NULL);
-
- /* get the expression and the print flag */
- expr = xlarg(&args);
- flag = (args ? xlarg(&args) : true);
- xllastarg(args);
-
- /* establish an execution context */
- xlbegin(&cntxt,CF_ERROR,flag);
-
- /* check for error */
- if (setjmp(cntxt.c_jmpbuf))
- val = NIL;
-
- /* otherwise, evaluate the expression */
- else {
- expr = xleval(expr);
- val = consa(expr);
- }
- xlend(&cntxt);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* xevalhook - eval hook function */
- NODE *xevalhook(args)
- NODE *args;
- {
- NODE ***oldstk,*expr,*ehook,*ahook,*env,*newehook,*newahook,*newenv,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&expr,&ehook,&ahook,&env,&newehook,&newahook,&newenv,(NODE **)NULL);
-
- /* get the expression, the new hook functions and the environment */
- expr = xlarg(&args);
- newehook = xlarg(&args);
- newahook = xlarg(&args);
- newenv = (args ? xlarg(&args) : xlenv);
- xllastarg(args);
-
- /* bind *evalhook* and *applyhook* to the hook functions */
- ehook = getvalue(s_evalhook);
- setvalue(s_evalhook,newehook);
- ahook = getvalue(s_applyhook);
- setvalue(s_applyhook,newahook);
- env = xlenv;
- xlenv = newenv;
-
- /* evaluate the expression (bypassing *evalhook*) */
- val = xlxeval(expr);
-
- /* unbind the hook variables */
- setvalue(s_evalhook,ehook);
- setvalue(s_applyhook,ahook);
- xlenv = env;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* dobindings - handle bindings for let/let*, prog/prog*, do/do* */
- LOCAL dobindings(blist,env)
- NODE *blist,*env;
- {
- NODE ***oldstk,*list,*bnd,*sym,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&list,&bnd,&sym,&val,(NODE **)NULL);
-
- /* bind each symbol in the list of bindings */
- for (list = blist; consp(list); list = cdr(list)) {
-
- /* get the next binding */
- bnd = car(list);
-
- /* handle a symbol */
- if (symbolp(bnd)) {
- sym = bnd;
- val = NIL;
- }
-
- /* handle a list of the form (symbol expr) */
- else if (consp(bnd)) {
- sym = xlmatch(SYM,&bnd);
- val = xlevarg(&bnd);
- }
- else
- xlfail("bad binding");
-
- /* bind the value to the symbol */
- xlbind(sym,val,env);
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
- }
-
- /* doupdates - handle updates for do/do* */
- doupdates(blist,pflag)
- NODE *blist; int pflag;
- {
- NODE ***oldstk,*plist,*list,*bnd,*sym,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&plist,&list,&bnd,&sym,&val,(NODE **)NULL);
-
- /* bind each symbol in the list of bindings */
- for (list = blist; consp(list); list = cdr(list)) {
-
- /* get the next binding */
- bnd = car(list);
-
- /* handle a list of the form (symbol expr) */
- if (consp(bnd)) {
- sym = xlmatch(SYM,&bnd);
- bnd = cdr(bnd);
- if (bnd) {
- val = xlevarg(&bnd);
- if (pflag) {
- plist = consd(plist);
- rplaca(plist,cons(sym,val));
- }
- else
- xlsetvalue(sym,val);
- }
- }
- }
-
- /* set the values for parallel updates */
- for (; plist; plist = cdr(plist))
- xlsetvalue(car(car(plist)),cdr(car(plist)));
-
- /* restore the previous stack frame */
- xlstack = oldstk;
- }
-
- /* tagblock - execute code within a block and tagbody */
- int tagblock(code,pval)
- NODE *code,**pval;
- {
- NODE ***oldstk,*arg;
- CONTEXT cntxt;
- int type,sts;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,(NODE **)NULL);
-
- /* initialize */
- arg = code;
-
- /* establish an execution context */
- xlbegin(&cntxt,CF_GO|CF_RETURN,arg);
-
- /* check for a 'return' */
- if ((type = setjmp(cntxt.c_jmpbuf)) == CF_RETURN) {
- *pval = xlvalue;
- sts = TRUE;
- }
-
- /* otherwise, enter the body */
- else {
-
- /* check for a 'go' */
- if (type == CF_GO)
- arg = xlvalue;
-
- /* evaluate each expression in the body */
- while (consp(arg))
- if (consp(car(arg)))
- xlevarg(&arg);
- else
- arg = cdr(arg);
-
- /* fell out the bottom of the loop */
- *pval = NIL;
- sts = FALSE;
- }
- xlend(&cntxt);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return status */
- return (sts);
- }
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'xldbug.c'
- then
- echo shar: will not over-write existing file "'xldbug.c'"
- else
- cat << \SHAR_EOF > 'xldbug.c'
- /* xldebug - xlisp debugging support */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
-
- #include "xlisp.h"
-
- /* external variables */
- extern long total;
- extern int xldebug;
- extern int xltrace;
- extern int xlsample;
- extern NODE *s_unbound;
- extern NODE *s_stdin,*s_stdout;
- extern NODE *s_tracenable,*s_tlimit,*s_breakenable;
- extern NODE ***xlstack;
- extern NODE *true;
- extern NODE **trace_stack;
- extern char buf[];
-
- /* external routines */
- extern char *malloc();
-
- /* forward declarations */
- FORWARD NODE *stacktop();
-
- /* xlfail - xlisp error handler */
- /*VARARGS*/
- xlfail(emsg)
- char *emsg;
- {
- xlerror(emsg,stacktop());
- }
-
- /* xlabort - xlisp serious error handler */
- xlabort(emsg)
- char *emsg;
- {
- xlsignal(emsg,s_unbound);
- }
-
- /* xlbreak - enter a break loop */
- xlbreak(emsg,arg)
- char *emsg; NODE *arg;
- {
- breakloop("break",NULL,emsg,arg,TRUE);
- }
-
- /* xlerror - handle a fatal error */
- xlerror(emsg,arg)
- char *emsg; NODE *arg;
- {
- doerror(NULL,emsg,arg,FALSE);
- }
-
- /* xlcerror - handle a recoverable error */
- xlcerror(cmsg,emsg,arg)
- char *cmsg,*emsg; NODE *arg;
- {
- doerror(cmsg,emsg,arg,TRUE);
- }
-
- /* xlerrprint - print an error message */
- xlerrprint(hdr,cmsg,emsg,arg)
- char *hdr,*cmsg,*emsg; NODE *arg;
- {
- sprintf(buf,"%s: %s",hdr,emsg); stdputstr(buf);
- if (arg != s_unbound) { stdputstr(" - "); stdprint(arg); }
- else xlterpri(getvalue(s_stdout));
- if (cmsg) { sprintf(buf,"if continued: %s\n",cmsg); stdputstr(buf); }
- }
-
- /* doerror - handle xlisp errors */
- LOCAL doerror(cmsg,emsg,arg,cflag)
- char *cmsg,*emsg; NODE *arg; int cflag;
- {
- /* make sure the break loop is enabled */
- if (getvalue(s_breakenable) == NIL)
- xlsignal(emsg,arg);
-
- /* call the debug read-eval-print loop */
- breakloop("error",cmsg,emsg,arg,cflag);
- }
-
- /* breakloop - the debug read-eval-print loop */
- LOCAL int breakloop(hdr,cmsg,emsg,arg,cflag)
- char *hdr,*cmsg,*emsg; NODE *arg; int cflag;
- {
- NODE ***oldstk,*expr,*val;
- CONTEXT cntxt;
- int type;
-
- /* print the error message */
- xlerrprint(hdr,cmsg,emsg,arg);
-
- /* flush the input buffer */
- xlflush();
-
- /* do the back trace */
- if (getvalue(s_tracenable)) {
- val = getvalue(s_tlimit);
- xlbaktrace(fixp(val) ? (int)getfixnum(val) : -1);
- }
-
- /* create a new stack frame */
- oldstk = xlsave(&expr,(NODE **)NULL);
-
- /* increment the debug level */
- xldebug++;
-
- /* debug command processing loop */
- xlbegin(&cntxt,CF_ERROR|CF_CLEANUP|CF_CONTINUE,true);
- for (type = 0; type == 0; ) {
-
- /* setup the continue trap */
- if (type = setjmp(cntxt.c_jmpbuf))
- switch (type) {
- case CF_ERROR:
- xlflush();
- type = 0;
- continue;
- case CF_CLEANUP:
- continue;
- case CF_CONTINUE:
- if (cflag) {
- stdputstr("[ continue from break loop ]\n");
- continue;
- }
- else xlabort("this error can't be continued");
- }
-
- /* read an expression and check for eof */
- if (!xlread(getvalue(s_stdin),&expr,FALSE)) {
- type = CF_CLEANUP;
- break;
- }
-
- /* evaluate the expression */
- expr = xleval(expr);
-
- /* print it */
- xlprint(getvalue(s_stdout),expr,TRUE);
- xlterpri(getvalue(s_stdout));
- }
- xlend(&cntxt);
-
- /* decrement the debug level */
- xldebug--;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* check for aborting to the previous level */
- if (type == CF_CLEANUP) {
- stdputstr("[ abort to previous level ]\n");
- xlsignal(NULL,NIL);
- }
- }
-
- /* stacktop - return the top node on the stack */
- LOCAL NODE *stacktop()
- {
- return (xltrace >= 0 && xltrace < TDEPTH ? trace_stack[xltrace] : s_unbound);
- }
-
- /* baktrace - do a back trace */
- xlbaktrace(n)
- int n;
- {
- int i;
-
- for (i = xltrace; (n < 0 || n--) && i >= 0; i--)
- if (i < TDEPTH)
- stdprint(trace_stack[i]);
- }
-
- /* xldinit - debug initialization routine */
- xldinit()
- {
- if ((trace_stack = (NODE **)malloc(TDEPTH * sizeof(NODE *))) == NULL) {
- printf("insufficient memory");
- osfinish();
- exit(1);
- }
- total += (long)(TDEPTH * sizeof(NODE *));
- xlsample = 0;
- xltrace = -1;
- xldebug = 0;
- }
-
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'xldmem.c'
- then
- echo shar: will not over-write existing file "'xldmem.c'"
- else
- cat << \SHAR_EOF > 'xldmem.c'
- /* xldmem - xlisp dynamic memory management routines */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
-
- #include "xlisp.h"
-
- /* useful definitions */
- #define ALLOCSIZE (sizeof(struct segment) + (anodes-1) * sizeof(NODE))
-
- /* external variables */
- extern NODE ***xlstack,***xlstkbase,***xlstktop;
- extern NODE *obarray;
- extern NODE *xlenv;
- extern long total;
- extern int anodes,nnodes,nsegs,nfree,gccalls;
- extern struct segment *segs;
- extern NODE *fnodes;
- extern char buf[];
-
- /* external procedures */
- extern char *malloc();
- extern char *calloc();
-
- /* forward declarations */
- FORWARD NODE *newnode();
- FORWARD char *strsave();
- FORWARD char *stralloc();
-
- /* cons - construct a new cons node */
- NODE *cons(x,y)
- NODE *x,*y;
- {
- NODE *val;
- val = newnode(LIST);
- rplaca(val,x);
- rplacd(val,y);
- return (val);
- }
-
- /* consa - (cons x nil) */
- NODE *consa(x)
- NODE *x;
- {
- NODE *val;
- val = newnode(LIST);
- rplaca(val,x);
- return (val);
- }
-
- /* consd - (cons nil x) */
- NODE *consd(x)
- NODE *x;
- {
- NODE *val;
- val = newnode(LIST);
- rplacd(val,x);
- return (val);
- }
-
- /* cvstring - convert a string to a string node */
- NODE *cvstring(str)
- char *str;
- {
- NODE ***oldstk,*val;
- oldstk = xlsave(&val,(NODE **)NULL);
- val = newnode(STR);
- val->n_str = strsave(str);
- val->n_strtype = DYNAMIC;
- xlstack = oldstk;
- return (val);
- }
-
- /* cvcstring - convert a constant string to a string node */
- NODE *cvcstring(str)
- char *str;
- {
- NODE *val;
- val = newnode(STR);
- val->n_str = str;
- val->n_strtype = STATIC;
- return (val);
- }
-
- /* cvsymbol - convert a string to a symbol */
- NODE *cvsymbol(pname)
- char *pname;
- {
- NODE ***oldstk,*val;
- oldstk = xlsave(&val,(NODE **)NULL);
- val = newnode(SYM);
- val->n_symplist = newnode(LIST);
- rplaca(val->n_symplist,cvstring(pname));
- xlstack = oldstk;
- return (val);
- }
-
- /* cvcsymbol - convert a constant string to a symbol */
- NODE *cvcsymbol(pname)
- char *pname;
- {
- NODE ***oldstk,*val;
- oldstk = xlsave(&val,(NODE **)NULL);
- val = newnode(SYM);
- val->n_symplist = newnode(LIST);
- rplaca(val->n_symplist,cvcstring(pname));
- xlstack = oldstk;
- return (val);
- }
-
- /* cvsubr - convert a function to a subr or fsubr */
- NODE *cvsubr(fcn,type)
- NODE *(*fcn)(); int type;
- {
- NODE *val;
- val = newnode(type);
- val->n_subr = fcn;
- return (val);
- }
-
- /* cvfile - convert a file pointer to a file */
- NODE *cvfile(fp)
- FILE *fp;
- {
- NODE *val;
- val = newnode(FPTR);
- setfile(val,fp);
- setsavech(val,0);
- return (val);
- }
-
- /* cvfixnum - convert an integer to a fixnum node */
- NODE *cvfixnum(n)
- FIXNUM n;
- {
- NODE *val;
- val = newnode(INT);
- val->n_int = n;
- return (val);
- }
-
- /* cvflonum - convert a floating point number to a flonum node */
- NODE *cvflonum(n)
- FLONUM n;
- {
- NODE *val;
- val = newnode(FLOAT);
- val->n_float = n;
- return (val);
- }
-
- /* newstring - allocate and initialize a new string */
- NODE *newstring(size)
- int size;
- {
- NODE ***oldstk,*val;
- oldstk = xlsave(&val,(NODE **)NULL);
- val = newnode(STR);
- val->n_str = stralloc(size);
- *getstring(val) = 0;
- val->n_strtype = DYNAMIC;
- xlstack = oldstk;
- return (val);
- }
-
- /* newobject - allocate and initialize a new object */
- NODE *newobject(cls,size)
- NODE *cls; int size;
- {
- NODE *val;
- val = newvector(size+1);
- setelement(val,0,cls);
- val->n_type = OBJ;
- return (val);
- }
-
- /* newvector - allocate and initialize a new vector node */
- NODE *newvector(size)
- int size;
- {
- NODE ***oldstk,*vect;
- int bsize;
-
- /* establish a new stack frame */
- oldstk = xlsave(&vect,(NODE **)NULL);
-
- /* allocate a vector node and set the size to zero (in case of gc) */
- vect = newnode(VECT);
- vect->n_vsize = 0;
-
- /* allocate memory for the vector */
- bsize = size * sizeof(NODE *);
- if ((vect->n_vdata = (NODE **) calloc(1,bsize)) == NULL) {
- findmem();
- if ((vect->n_vdata = (NODE **) calloc(1,bsize)) == NULL)
- xlfail("insufficient vector space");
- }
- vect->n_vsize = size;
- total += (long) bsize;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the new vector */
- return (vect);
- }
-
- /* newnode - allocate a new node */
- LOCAL NODE *newnode(type)
- int type;
- {
- NODE *nnode;
-
- /* get a free node */
- if ((nnode = fnodes) == NIL) {
- findmem();
- if ((nnode = fnodes) == NIL)
- xlabort("insufficient node space");
- }
-
- /* unlink the node from the free list */
- fnodes = cdr(nnode);
- nfree -= 1;
-
- /* initialize the new node */
- nnode->n_type = type;
- rplacd(nnode,NIL);
-
- /* return the new node */
- return (nnode);
- }
-
- /* stralloc - allocate memory for a string adding a byte for the terminator */
- LOCAL char *stralloc(size)
- int size;
- {
- char *sptr;
-
- /* allocate memory for the string copy */
- if ((sptr = malloc(size+1)) == NULL) {
- findmem();
- if ((sptr = malloc(size+1)) == NULL)
- xlfail("insufficient string space");
- }
- total += (long) (size+1);
-
- /* return the new string memory */
- return (sptr);
- }
-
- /* strsave - generate a dynamic copy of a string */
- LOCAL char *strsave(str)
- char *str;
- {
- char *sptr;
-
- /* create a new string */
- sptr = stralloc(strlen(str));
- strcpy(sptr,str);
-
- /* return the new string */
- return (sptr);
- }
-
- /* strfree - free a string UNUSED
- LOCAL strfree(str)
- char *str;
- {
- total -= (long) (strlen(str)+1);
- free(str);
- }
- */
-
- /* findmem - find more memory by collecting then expanding */
- findmem()
- {
- gc();
- if (nfree < anodes)
- addseg();
- }
-
- /* gc - garbage collect */
- gc()
- {
- NODE ***p;
- void mark();
-
- /* mark the obarray and the current environment */
- mark(obarray);
- mark(xlenv);
-
- /* mark the evaluation stack */
- for (p = xlstack; p < xlstktop; )
- mark(**p++);
-
- /* sweep memory collecting all unmarked nodes */
- sweep();
-
- /* count the gc call */
- gccalls++;
- }
-
- /* mark - mark all accessible nodes */
- void mark(ptr)
- NODE *ptr;
- {
- NODE *this,*prev,*tmp;
-
- /* just return on nil */
- if (ptr == NIL)
- return;
-
- /* initialize */
- prev = NIL;
- this = ptr;
-
- /* mark this list */
- while (TRUE) {
-
- /* descend as far as we can */
- while (TRUE) {
-
- /* check for this node being marked */
- if (this->n_flags & MARK)
- break;
-
- /* mark it and its descendants */
- else {
-
- /* mark the node */
- this->n_flags |= MARK;
-
- /* follow the left sublist if there is one */
- if (livecar(this)) {
- this->n_flags |= LEFT;
- tmp = prev;
- prev = this;
- this = car(prev);
- rplaca(prev,tmp);
- }
-
- /* otherwise, follow the right sublist if there is one */
- else if (livecdr(this)) {
- this->n_flags &= ~LEFT;
- tmp = prev;
- prev = this;
- this = cdr(prev);
- rplacd(prev,tmp);
- }
- else
- break;
- }
- }
-
- /* backup to a point where we can continue descending */
- while (TRUE) {
-
- /* check for termination condition */
- if (prev == NIL)
- return;
-
- /* check for coming from the left side */
- if (prev->n_flags & LEFT)
- if (livecdr(prev)) {
- prev->n_flags &= ~LEFT;
- tmp = car(prev);
- rplaca(prev,this);
- this = cdr(prev);
- rplacd(prev,tmp);
- break;
- }
- else {
- tmp = prev;
- prev = car(tmp);
- rplaca(tmp,this);
- this = tmp;
- }
-
- /* otherwise, came from the right side */
- else {
- tmp = prev;
- prev = cdr(tmp);
- rplacd(tmp,this);
- this = tmp;
- }
- }
- }
- }
-
- /* vmark - mark a vector */
- vmark(n)
- NODE *n;
- {
- int i;
- for (i = 0; i < getsize(n); ++i)
- mark(getelement(n,i));
- }
-
- /* sweep - sweep all unmarked nodes and add them to the free list */
- LOCAL sweep()
- {
- struct segment *seg;
- NODE *p;
- int n;
-
- /* empty the free list */
- fnodes = NIL;
- nfree = 0;
-
- /* add all unmarked nodes */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; n--; p++)
- if (!(p->n_flags & MARK)) {
- switch (ntype(p)) {
- case STR:
- if (p->n_strtype == DYNAMIC && p->n_str != NULL) {
- total -= (long) (strlen(p->n_str)+1);
- free(p->n_str);
- }
- break;
- case FPTR:
- if (p->n_fp)
- fclose(p->n_fp);
- break;
- case VECT:
- if (p->n_vsize) {
- total -= (long) (p->n_vsize * sizeof(NODE **));
- free(p->n_vdata);
- }
- break;
- }
- p->n_type = FREE;
- p->n_flags = 0;
- rplaca(p,NIL);
- rplacd(p,fnodes);
- fnodes = p;
- nfree++;
- }
- else
- p->n_flags &= ~(MARK | LEFT);
- }
- }
-
- /* addseg - add a segment to the available memory */
- int addseg()
- {
- struct segment *newseg;
- NODE *p;
- int n;
-
- /* check for zero allocation */
- if (anodes == 0)
- return (FALSE);
-
- /* allocate a new segment */
- if ((newseg = (struct segment *) calloc(1,ALLOCSIZE)) != NULL) {
-
- /* initialize the new segment */
- newseg->sg_size = anodes;
- newseg->sg_next = segs;
- segs = newseg;
-
- /* add each new node to the free list */
- p = &newseg->sg_nodes[0];
- for (n = anodes; n--; ) {
- rplacd(p,fnodes);
- fnodes = p++;
- }
-
- /* update the statistics */
- total += (long) ALLOCSIZE;
- nnodes += anodes;
- nfree += anodes;
- nsegs++;
-
- /* return successfully */
- return (TRUE);
- }
- else
- return (FALSE);
- }
-
- /* livecar - do we need to follow the car? */
- LOCAL int livecar(n)
- NODE *n;
- {
- switch (ntype(n)) {
- case OBJ:
- case VECT:
- vmark(n);
- case SUBR:
- case FSUBR:
- case INT:
- case FLOAT:
- case STR:
- case FPTR:
- return (FALSE);
- case SYM:
- case LIST:
- return (car(n) != NIL);
- default:
- printf("bad node type (%d) found during left scan\n",ntype(n));
- osfinish ();
- exit(1);
- }
- /*NOTREACHED*/
- }
-
- /* livecdr - do we need to follow the cdr? */
- LOCAL int livecdr(n)
- NODE *n;
- {
- switch (ntype(n)) {
- case SUBR:
- case FSUBR:
- case INT:
- case FLOAT:
- case STR:
- case FPTR:
- case OBJ:
- case VECT:
- return (FALSE);
- case SYM:
- case LIST:
- return (cdr(n) != NIL);
- default:
- printf("bad node type (%d) found during right scan\n",ntype(n));
- osfinish ();
- exit(1);
- }
- /*NOTREACHED*/
- }
-
- /* stats - print memory statistics */
- stats()
- {
- sprintf(buf,"Nodes: %d\n",nnodes); stdputstr(buf);
- sprintf(buf,"Free nodes: %d\n",nfree); stdputstr(buf);
- sprintf(buf,"Segments: %d\n",nsegs); stdputstr(buf);
- sprintf(buf,"Allocate: %d\n",anodes); stdputstr(buf);
- sprintf(buf,"Total: %ld\n",total); stdputstr(buf);
- sprintf(buf,"Collections: %d\n",gccalls); stdputstr(buf);
- }
-
- /* xlminit - initialize the dynamic memory module */
- xlminit()
- {
- /* initialize our internal variables */
- anodes = NNODES;
- total = 0L;
- nnodes = nsegs = nfree = gccalls = 0;
- fnodes = NIL;
- segs = NULL;
-
- /* initialize structures that are marked by the collector */
- xlenv = obarray = NIL;
-
- /* allocate the evaluation stack */
- if ((xlstkbase = (NODE ***)malloc(EDEPTH * sizeof(NODE **))) == NULL) {
- printf("insufficient memory");
- osfinish ();
- exit(1);
- }
- total += (long)(EDEPTH * sizeof(NODE **));
- xlstack = xlstktop = xlstkbase + EDEPTH;
- }
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'xleval.c'
- then
- echo shar: will not over-write existing file "'xleval.c'"
- else
- cat << \SHAR_EOF > 'xleval.c'
- /* xleval - xlisp evaluator */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
-
- #include "xlisp.h"
-
- /* external variables */
- extern int xlsample;
- extern NODE ***xlstack,***xlstkbase,*xlenv;
- extern NODE *s_lambda,*s_macro;
- extern NODE *k_optional,*k_rest,*k_aux;
- extern NODE *s_evalhook,*s_applyhook;
- extern NODE *s_unbound;
- extern NODE *s_stdout;
-
- /* trace variables */
- extern NODE **trace_stack;
- extern int xltrace;
-
- /* forward declarations */
- FORWARD NODE *xlxeval();
- FORWARD NODE *evalhook();
- FORWARD NODE *evform();
- FORWARD NODE *evfun();
-
- /* xleval - evaluate an xlisp expression (checking for *evalhook*) */
- NODE *xleval(expr)
- NODE *expr;
- {
- /* check for control codes */
- if (--xlsample <= 0) {
- xlsample = SAMPLE;
- oscheck();
- }
-
- /* check for *evalhook* */
- if (getvalue(s_evalhook))
- return (evalhook(expr));
-
- /* add trace entry */
- if (++xltrace < TDEPTH)
- trace_stack[xltrace] = expr;
-
- /* check type of value */
- if (consp(expr))
- expr = evform(expr);
- else if (symbolp(expr))
- expr = xlgetvalue(expr);
-
- /* remove trace entry */
- --xltrace;
-
- /* return the value */
- return (expr);
- }
-
- /* xlxeval - evaluate an xlisp expression (bypassing *evalhook*) */
- NODE *xlxeval(expr)
- NODE *expr;
- {
- /* check type of value */
- if (consp(expr))
- expr = evform(expr);
- else if (symbolp(expr))
- expr = xlgetvalue(expr);
-
- /* return the value */
- return (expr);
- }
-
- /* xlapply - apply a function to a list of arguments */
- NODE *xlapply(fun,args)
- NODE *fun,*args;
- {
- NODE *env,*val;
-
- /* check for a null function */
- if (fun == NIL)
- xlfail("bad function");
-
- /* evaluate the function */
- if (subrp(fun))
- val = (*getsubr(fun))(args);
- else if (consp(fun)) {
- if (consp(car(fun))) {
- env = cdr(fun);
- fun = car(fun);
- }
- else
- env = xlenv;
- if (car(fun) != s_lambda)
- xlfail("bad function type");
- val = evfun(fun,args,env);
- }
- else
- xlfail("bad function");
-
- /* return the result value */
- return (val);
- }
-
- /* evform - evaluate a form */
- LOCAL NODE *evform(expr)
- NODE *expr;
- {
- NODE ***oldstk,*fun,*args,*env,*val,*type;
-
- /* create a stack frame */
- oldstk = xlsave(&fun,&args,(NODE **)NULL);
-
- /* get the function and the argument list */
- fun = car(expr);
- args = cdr(expr);
-
- /* evaluate the first expression */
- if ((fun = xleval(fun)) == NIL)
- xlfail("bad function");
-
- /* evaluate the function */
- if (subrp(fun) || fsubrp(fun)) {
- if (subrp(fun))
- args = xlevlist(args);
- val = (*getsubr(fun))(args);
- }
- else if (consp(fun)) {
- if (consp(car(fun))) {
- env = cdr(fun);
- fun = car(fun);
- }
- else
- env = xlenv;
- if ((type = car(fun)) == s_lambda) {
- args = xlevlist(args);
- val = evfun(fun,args,env);
- }
- else if (type == s_macro) {
- args = evfun(fun,args,env);
- val = xleval(args);
- }
- else
- xlfail("bad function type");
- }
- else if (objectp(fun))
- val = xlsend(fun,args);
- else
- xlfail("bad function");
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result value */
- return (val);
- }
-
- /* evalhook - call the evalhook function */
- LOCAL NODE *evalhook(expr)
- NODE *expr;
- {
- NODE ***oldstk,*ehook,*ahook,*args,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&ehook,&ahook,&args,(NODE **)NULL);
-
- /* make an argument list */
- args = consa(expr);
- rplacd(args,consa(xlenv));
-
- /* rebind the hook functions to nil */
- ehook = getvalue(s_evalhook);
- setvalue(s_evalhook,NIL);
- ahook = getvalue(s_applyhook);
- setvalue(s_applyhook,NIL);
-
- /* call the hook function */
- val = xlapply(ehook,args);
-
- /* unbind the symbols */
- setvalue(s_evalhook,ehook);
- setvalue(s_applyhook,ahook);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the value */
- return (val);
- }
-
- /* xlevlist - evaluate a list of arguments */
- NODE *xlevlist(args)
- NODE *args;
- {
- NODE ***oldstk,*src,*dst,*new,*val;
- NODE *last = NIL;
-
- /* create a stack frame */
- oldstk = xlsave(&src,&dst,(NODE **)NULL);
-
- /* initialize */
- src = args;
-
- /* evaluate each argument */
- for (val = NIL; src; src = cdr(src)) {
-
- /* check this entry */
- if (!consp(src))
- xlfail("bad argument list");
-
- /* allocate a new list entry */
- new = consa(NIL);
- if (val)
- rplacd(last,new);
- else
- val = dst = new;
- rplaca(new,xleval(car(src)));
- last = new;
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the new list */
- return (val);
- }
-
- /* xlunbound - signal an unbound variable error */
- xlunbound(sym)
- NODE *sym;
- {
- xlcerror("try evaluating symbol again","unbound variable",sym);
- }
-
- /* evfun - evaluate a function */
- LOCAL NODE *evfun(fun,args,env)
- NODE *fun,*args,*env;
- {
- NODE ***oldstk,*oldenv,*newenv,*cptr,*fargs,*val;
-
- /* create a stack frame */
- oldstk = xlsave(&oldenv,&newenv,&cptr,(NODE **)NULL);
-
- /* skip the function type */
- if ((fun = cdr(fun)) == NIL || !consp(fun))
- xlfail("bad function definition");
-
- /* get the formal argument list */
- if ((fargs = car(fun)) && !consp(fargs))
- xlfail("bad formal argument list");
-
- /* create a new environment frame */
- newenv = xlframe(env);
- oldenv = xlenv;
-
- /* bind the formal parameters */
- xlabind(fargs,args,newenv);
- xlenv = newenv;
-
- /* execute the code */
- for (cptr = cdr(fun); cptr; )
- val = xlevarg(&cptr);
-
- /* restore the environment */
- xlenv = oldenv;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result value */
- return (val);
- }
-
- /* xlabind - bind the arguments for a function */
- xlabind(fargs,aargs,env)
- NODE *fargs,*aargs,*env;
- {
- NODE *arg;
-
- /* evaluate and bind each required argument */
- while (consp(fargs) && !iskeyword(arg = car(fargs)) && consp(aargs)) {
-
- /* bind the formal variable to the argument value */
- xlbind(arg,car(aargs),env);
-
- /* move the argument list pointers ahead */
- fargs = cdr(fargs);
- aargs = cdr(aargs);
- }
-
- /* check for the '&optional' keyword */
- if (consp(fargs) && car(fargs) == k_optional) {
- fargs = cdr(fargs);
-
- /* bind the arguments that were supplied */
- while (consp(fargs) && !iskeyword(arg = car(fargs)) && consp(aargs)) {
-
- /* bind the formal variable to the argument value */
- xlbind(arg,car(aargs),env);
-
- /* move the argument list pointers ahead */
- fargs = cdr(fargs);
- aargs = cdr(aargs);
- }
-
- /* bind the rest to nil */
- while (consp(fargs) && !iskeyword(arg = car(fargs))) {
-
- /* bind the formal variable to nil */
- xlbind(arg,NIL,env);
-
- /* move the argument list pointer ahead */
- fargs = cdr(fargs);
- }
- }
-
- /* check for the '&rest' keyword */
- if (consp(fargs) && car(fargs) == k_rest) {
- fargs = cdr(fargs);
- if (consp(fargs) && (arg = car(fargs)) && !iskeyword(arg))
- xlbind(arg,aargs,env);
- else
- xlfail("symbol missing after &rest");
- fargs = cdr(fargs);
- aargs = NIL;
- }
-
- /* check for the '&aux' keyword */
- if (consp(fargs) && car(fargs) == k_aux)
- while ((fargs = cdr(fargs)) != NIL && consp(fargs))
- xlbind(car(fargs),NIL,env);
-
- /* make sure the correct number of arguments were supplied */
- if (fargs != aargs)
- xlfail(fargs ? "too few arguments" : "too many arguments");
- }
-
- /* iskeyword - check to see if a symbol is a keyword */
- LOCAL int iskeyword(sym)
- NODE *sym;
- {
- return (sym == k_optional || sym == k_rest || sym == k_aux);
- }
-
- /* xlsave - save nodes on the stack */
- /*VARARGS*/
- NODE ***xlsave(n)
- NODE **n;
- {
- NODE ***oldstk,***nptr;
-
- /* save the old stack pointer */
- oldstk = xlstack;
-
- /* save each node pointer */
- for (nptr = &n; *nptr; nptr++) {
- if (xlstack <= xlstkbase)
- xlabort("evaluation stack overflow");
- *--xlstack = *nptr;
- **nptr = NIL;
- }
-
- /* return the old stack pointer */
- return (oldstk);
- }
-
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-
-